package encounter;

import main.Hero;
import main.Logger;
import main.RandomProvider;
import monster.Monster;

public class Combat {
    private final Hero hero;
    private final Monster enemy;
    
    private int heroHits = 0;
    private int enemyHits = 0;
    private boolean runAway = false;

    public Combat(Hero hero, Monster enemy) {
        this.hero = hero;
        this.enemy = enemy;
    }

    public boolean fight() {
        Logger.log("-----------------------------");

        Logger.log(hero + " fights " + enemy + ".");

        int sneakRoll = RandomProvider.roll(hero.getSneak());
        int spotRoll = RandomProvider.roll(enemy.getSpot());

        if (sneakRoll > spotRoll) {
            Logger.log(hero + " sneaks on " + enemy + ".");
            hero.addEvent("Sneaks on " + enemy);
            // TODO hero can decide to avoid combat

            hero.updateEnergy(-0.01);
            enemy.updateEnergy(-0.01);

            int sneakAttack = RandomProvider.roll(hero.getCombat()) + RandomProvider.roll(10);
            int defence = RandomProvider.roll(enemy.getCombat());
            if (sneakAttack > defence) {
                Logger.log(hero + " sneak hits " + enemy);
                enemy.updateHealth(-1);
                enemyHits++;
            }
        }

        while (hero.isAlive() && enemy.isAlive()) {
            hero.updateEnergy(-0.01);
            enemy.updateEnergy(-0.01);

            if ((heroHits >= 2 && enemyHits == 0) || (heroHits - enemyHits > 2) || hero.getHealth() <= 3) {
                int runRoll = RandomProvider.roll(hero.getSpeed());
                int pursueRoll = RandomProvider.roll(enemy.getSpeed());

                if (runRoll > pursueRoll) {
                    Logger.log(hero + " runs away.");
                    hero.addEvent("Runs away from " + enemy + ".");
                    hero.updateEnergy(-0.05);
                    runAway = true;
                }
            } else if (enemyHits > 0 && RandomProvider.chance(0.25)) {
                int runRoll = RandomProvider.roll(enemy.getSpeed());
                int pursueRoll = RandomProvider.roll(hero.getSpeed());

                if (runRoll > pursueRoll) {
                    Logger.log(enemy + " runs away.");
                    hero.addEvent("Defeats " + enemy + ".");
                    enemy.updateEnergy(-0.05);
                    runAway = true;
                }
            }

            if (runAway) {
                break;
            }

            int heroRoll = RandomProvider.roll(hero.getCombat());
            int enemyRoll = RandomProvider.roll(enemy.getCombat());

            if (heroRoll > enemyRoll) {
                Logger.log(hero + " hits " + enemy);
                enemy.updateHealth(-1);
                enemyHits++;
            } else if (heroRoll < enemyRoll) {
                Logger.log(enemy + " hits " + hero);
                hero.updateHealth(-1);
                heroHits++;
            }
        }

        boolean heroWins = false;
        if (!runAway) {
            if (hero.isAlive()) {
                Logger.log(hero + " defeats " + enemy + ".");
                hero.addEvent("Defeats " + enemy + ".");
                hero.addTrophy(enemy);
                heroWins = true;
            } else {
                Logger.log(enemy + " defeats " + hero + ".");
                hero.addEvent("Is defeated by " + enemy + "!");
            }
        }

        Logger.log("-----------------------------");
        return heroWins;
    }
}
